// Package service
// Created by GoLand
// @User: lenora
// @Date: 2024/8/16
// @Time: 11:08

package service

import (
	"camp/microbook/internal/domain"
	"camp/microbook/internal/repository"
	"camp/microbook/pkg/logger"
	"context"
	"time"
)

type JobService interface {
	Preempt(ctx context.Context) (domain.Job, error)
	ResetNextTime(ctx context.Context, job domain.Job) error
}

type CronJobService struct {
	repo repository.CronJobRepository
	l    logger.Logger
}

func NewCronJobService(repo repository.CronJobRepository, l logger.Logger) JobService {
	return &CronJobService{repo: repo, l: l}
}

func (svc *CronJobService) ResetNextTime(ctx context.Context, job domain.Job) error {
	return svc.repo.ResetNextTime(ctx, job.Id, job.Next())
}

func (svc *CronJobService) Preempt(ctx context.Context) (domain.Job, error) {
	//	抢占
	job, err := svc.repo.Preempt(ctx)
	if err != nil {
		return domain.Job{}, err
	}

	//完成后释放
	job.CancelFunc = func() {
		//由repo执行释放的业务
		//新建ctx,避免抢占的ctx过期
		canCtx, cancel := context.WithTimeout(context.Background(), time.Second)
		defer cancel()
		if err := svc.repo.Release(canCtx, job.Id); err != nil {
			svc.l.Error("release cron job failed",
				logger.Uint64("job id", job.Id),
				logger.Error(err),
			)
		}
		//释放失败可记录日志
	}
	return job, err
}
